package edu.nju.mutest.mutator;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.expr.*;
import edu.nju.mutest.util.CollectorUtil;
import edu.nju.mutest.visitor.collector.BasicTypeExpressionCollector;

import java.util.List;
import java.util.Random;

public class NumericLiteralMutator extends AbstractMutator{

    public NumericLiteralMutator(CompilationUnit cu) {
        super(cu);
    }

    @Override
    public List<CompilationUnit> mutate() {
        if (mutPoints == null) {
            mutPoints = CollectorUtil.collect(new BasicTypeExpressionCollector(), this.origCU);
        }

        Random rand = new Random();

        for (Expression mp : mutPoints) {
            if (mp.isIntegerLiteralExpr()) {
                int val = Integer.parseInt(mp.asIntegerLiteralExpr().getValue());
                replaceNode(mp, new IntegerLiteralExpr(Integer.toString(val + 1)));
                replaceNode(mp, new IntegerLiteralExpr(Integer.toString(val - 1)));
                replaceNode(mp, new IntegerLiteralExpr(Integer.toString(rand.nextInt())));
            }
            if (mp.isLongLiteralExpr()) {
                long val = Long.parseLong(mp.asLongLiteralExpr().getValue());
                replaceNode(mp, new LongLiteralExpr(Long.toString(val + 1)));
                replaceNode(mp, new LongLiteralExpr(Long.toString(val - 1)));
                replaceNode(mp, new LongLiteralExpr(Long.toString(rand.nextLong())));
            }
            if (mp.isDoubleLiteralExpr()) {
                double val = Double.parseDouble(mp.asDoubleLiteralExpr().getValue());
                replaceNode(mp, new DoubleLiteralExpr(Double.toString(val * 0.99)));
                replaceNode(mp, new DoubleLiteralExpr(Double.toString(val * 1.01)));
                double randVal = rand.nextDouble();
                if (randVal != 0) {
                    replaceNode(mp, new DoubleLiteralExpr(Double.toString(val / randVal)));
                    replaceNode(mp, new DoubleLiteralExpr(Double.toString(-val / randVal)));
                }
            }
        }
        return mutants;
    }
}
